﻿using Makaretu.Dns;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace BamiTech.AirServer
{
    public class AirPlayServer_mdns
    {
        public const string AirPlayType = "_airplay._tcp";
        public const string AirTunesType = "_raop._tcp";

        private MulticastService _mdns = null;
        private ServiceDiscovery _sd = null;
        private readonly string _instance = string.Empty;
        private readonly ushort _airTunesPort;
        private readonly ushort _airPlayPort;
        private readonly string _deviceId;

        public static byte[] bytesProperties { get; private set; }

        public AirPlayServer_mdns(string instance, ushort airTunesPort = 5000, ushort airPlayPort = 7000)
        {
            _instance = instance;
            _airTunesPort = airTunesPort;
            _airPlayPort = airPlayPort;
            _deviceId = Consts.mac_address;
        }

        public static byte[] Combine(IEnumerable<byte[]> arrays)
        {
            byte[] ret = new byte[arrays.Sum(x => x.Length)];
            int offset = 0;
            foreach (byte[] data in arrays)
            {
                Buffer.BlockCopy(data, 0, ret, offset, data.Length);
                offset += data.Length;
            }
            return ret;
        }

        public Task StartMdnsAsync()
        {
            if (string.IsNullOrWhiteSpace(_deviceId))
            {
                throw new ArgumentNullException(_deviceId);
            }

            _mdns = new MulticastService();
            _sd = new ServiceDiscovery(_mdns);

            foreach (var ip in MulticastService.GetIPAddresses())
            {
                Console.WriteLine($"IP address {ip}");
            }

            _mdns.NetworkInterfaceDiscovered += (s, e) =>
            {
                foreach (var nic in e.NetworkInterfaces)
                {
                    Console.WriteLine($"NIC '{nic.Name}'");
                }
            };

            var airPlay = new ServiceProfile(_instance, AirPlayType, _airPlayPort);
            Dictionary<string, string> dicProperties = new Dictionary<string, string>()
            {
                { "deviceid", _deviceId },
                { "features", Consts.AIRPLAY_FEATURES },
                { "flags", "0x4" },
                { "model", "AppleTV3,1" },
                { "pk", $"{Consts.AIRPLAY_PK}" },
                { "pi",  $"{Consts.AIRPLAY_PI}" },
                { "srcvers", "220.68" },
                { "vv", "2" }
            };

            foreach(var pair in dicProperties)
            {
                airPlay.AddProperty(pair.Key, pair.Value);
            }
            
            var bytesList = dicProperties.Select(item => $"{item.Key}={item.Value}")
                            .Select(item => Encoding.UTF8.GetBytes(item))
                            .Select(item =>
                                    {
                                        byte[] r = new byte[item.Length + 1];
                                        r[0] = (byte)item.Length;
                                        Array.Copy(item, 0, r, 1, item.Length);
                                        return r;
                                    });

            bytesProperties = Combine(bytesList);

            _sd.Advertise(airPlay);
            _mdns.Start();
            return Task.CompletedTask;
        }

    }
}
